/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.configuration.beanutils;
import java.util.Map;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.SubnodeConfiguration;
import org.apache.commons.configuration.tree.ConfigurationNode;
import junit.framework.TestCase;
/**
* Test class for XMLBeanDeclaration.
*
* @since 1.3
* @author Oliver Heger
* @version $Id: TestXMLBeanDeclaration.java 670739 2008-06-23 20:36:37Z oheger $
*/
public class TestXMLBeanDeclaration extends TestCase
{
/** An array with some test properties. */
static final String[] TEST_PROPS =
{ "firstName", "lastName", "department", "age", "hobby"};
/** An array with the values for the test properties. */
static final String[] TEST_VALUES =
{ "John", "Smith", "Engineering", "42", "TV"};
/** An array with the names of nested (complex) properties. */
static final String[] COMPLEX_PROPS =
{ "address", "car"};
/** An array with the names of the classes of the complex properties. */
static final String[] COMPLEX_CLASSES =
{ "org.apache.commons.configuration.test.AddressTest",
"org.apache.commons.configuration.test.CarTest"};
/** An array with the property names of the complex properties. */
static final String[][] COMPLEX_ATTRIBUTES =
{
{ "street", "zip", "city", "country"},
{ "brand", "color"}};
/** An array with the values of the complex properties. */
static final String[][] COMPLEX_VALUES =
{
{ "Baker Street", "12354", "London", "UK"},
{ "Bentley", "silver"}};
/** Constant for the key with the bean declaration. */
static final String KEY = "myBean";
/** Constant for the section with the variables.*/
static final String VARS = "variables.";
/** Stores the object to be tested. */
XMLBeanDeclaration decl;
/**
* Tests creating a declaration from a null node. This should cause an
* exception.
*/
public void testInitFromNullNode()
{
try
{
decl = new XMLBeanDeclaration(new HierarchicalConfiguration().configurationAt(null),
(ConfigurationNode) null);
fail("Could init declaration with null node!");
}
catch (IllegalArgumentException iex)
{
// ok
}
}
/**
* Tests creating a declaration from a null configuration. This should cause
* an exception.
*/
public void testInitFromNullConfiguration()
{
try
{
decl = new XMLBeanDeclaration((HierarchicalConfiguration) null);
fail("Could init declaration with null configuration!");
}
catch (IllegalArgumentException iex)
{
// ok
}
}
/**
* Tests creating a declaration from a null configuration with a key. This
* should cause an exception.
*/
public void testInitFromNullConfigurationAndKey()
{
try
{
decl = new XMLBeanDeclaration(null, KEY);
fail("Could init declaration with null configuration and key!");
}
catch (IllegalArgumentException iex)
{
// ok
}
}
/**
* Tests creating a declaration from a null configuration with a node. This
* should cause an exception.
*/
public void testInitFromNullConfigurationAndNode()
{
try
{
decl = new XMLBeanDeclaration(null, new HierarchicalConfiguration()
.getRoot());
fail("Could init declaration with null configuration and node!");
}
catch (IllegalArgumentException iex)
{
// ok
}
}
/**
* Tests fetching the bean's class name.
*/
public void testGetBeanClassName()
{
HierarchicalConfiguration config = new HierarchicalConfiguration();
config.addProperty(KEY + "[@config-class]", getClass().getName());
decl = new XMLBeanDeclaration(config, KEY);
assertEquals("Wrong class name", getClass().getName(), decl
.getBeanClassName());
}
/**
* Tests fetching the bean's class name if it is undefined.
*/
public void testGetBeanClassNameUndefined()
{
decl = new XMLBeanDeclaration(new HierarchicalConfiguration());
assertNull(decl.getBeanClassName());
}
/**
* Tests fetching the name of the bean factory.
*/
public void testGetBeanFactoryName()
{
HierarchicalConfiguration config = new HierarchicalConfiguration();
config.addProperty(KEY + "[@config-factory]", "myFactory");
decl = new XMLBeanDeclaration(config, KEY);
assertEquals("Wrong factory name", "myFactory", decl
.getBeanFactoryName());
}
/**
* Tests fetching the name of the bean factory if it is undefined.
*/
public void testGetBeanFactoryNameUndefined()
{
decl = new XMLBeanDeclaration(new HierarchicalConfiguration());
assertNull(decl.getBeanFactoryName());
}
/**
* Tests fetching the paramter for the bean factory.
*/
public void testGetBeanFactoryParameter()
{
HierarchicalConfiguration config = new HierarchicalConfiguration();
config
.addProperty(KEY + "[@config-factoryParam]",
"myFactoryParameter");
decl = new XMLBeanDeclaration(config, KEY);
assertEquals("Wrong factory parameter", "myFactoryParameter", decl
.getBeanFactoryParameter());
}
/**
* Tests fetching the paramter for the bean factory if it is undefined.
*/
public void testGetBeanFactoryParameterUndefined()
{
decl = new XMLBeanDeclaration(new HierarchicalConfiguration());
assertNull(decl.getBeanFactoryParameter());
}
/**
* Tests if the bean's properties are correctly extracted from the
* configuration object.
*/
public void testGetBeanProperties()
{
HierarchicalConfiguration config = new HierarchicalConfiguration();
setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
decl = new XMLBeanDeclaration(config, KEY);
checkProperties(decl, TEST_PROPS, TEST_VALUES);
}
/**
* Tests obtaining the bean's properties when reserved attributes are
* involved. These should be ignored.
*/
public void testGetBeanPropertiesWithReservedAttributes()
{
HierarchicalConfiguration config = new HierarchicalConfiguration();
setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
config.addProperty(KEY + "[@config-testattr]", "yes");
config.addProperty(KEY + "[@config-anothertest]", "this, too");
decl = new XMLBeanDeclaration(config, KEY);
checkProperties(decl, TEST_PROPS, TEST_VALUES);
}
/**
* Tests fetching properties if none are defined.
*/
public void testGetBeanPropertiesEmpty()
{
decl = new XMLBeanDeclaration(new HierarchicalConfiguration());
Map props = decl.getBeanProperties();
assertTrue("Properties found", props == null || props.isEmpty());
}
/**
* Creates a configuration with data for testing nested bean declarations.
* @return the initialized test configuration
*/
private HierarchicalConfiguration prepareNestedBeanDeclarations()
{
HierarchicalConfiguration config = new HierarchicalConfiguration();
setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
for (int i = 0; i < COMPLEX_PROPS.length; i++)
{
setupBeanDeclaration(config, KEY + '.' + COMPLEX_PROPS[i],
COMPLEX_ATTRIBUTES[i], COMPLEX_VALUES[i]);
config.addProperty(
KEY + '.' + COMPLEX_PROPS[i] + "[@config-class]",
COMPLEX_CLASSES[i]);
}
return config;
}
/**
* Tests fetching nested bean declarations.
*/
public void testGetNestedBeanDeclarations()
{
HierarchicalConfiguration config = prepareNestedBeanDeclarations();
decl = new XMLBeanDeclaration(config, KEY);
checkProperties(decl, TEST_PROPS, TEST_VALUES);
Map nested = decl.getNestedBeanDeclarations();
assertEquals("Wrong number of nested declarations",
COMPLEX_PROPS.length, nested.size());
for (int i = 0; i < COMPLEX_PROPS.length; i++)
{
XMLBeanDeclaration d = (XMLBeanDeclaration) nested
.get(COMPLEX_PROPS[i]);
assertNotNull("No declaration found for " + COMPLEX_PROPS[i], d);
checkProperties(d, COMPLEX_ATTRIBUTES[i], COMPLEX_VALUES[i]);
assertEquals("Wrong bean class", COMPLEX_CLASSES[i], d
.getBeanClassName());
}
}
/**
* Tests whether the factory method for creating nested bean declarations
* gets called.
*/
public void testGetNestedBeanDeclarationsFactoryMethod()
{
HierarchicalConfiguration config = prepareNestedBeanDeclarations();
decl = new XMLBeanDeclaration(config, KEY)
{
protected BeanDeclaration createBeanDeclaration(
ConfigurationNode node)
{
return new XMLBeanDeclarationTestImpl(getConfiguration()
.configurationAt(node.getName()), node);
}
};
Map nested = decl.getNestedBeanDeclarations();
for (int i = 0; i < COMPLEX_PROPS.length; i++)
{
Object d = nested.get(COMPLEX_PROPS[i]);
assertTrue("Wrong class for bean declaration: " + d,
d instanceof XMLBeanDeclarationTestImpl);
}
}
/**
* Tests fetching nested bean declarations if none are defined.
*/
public void testGetNestedBeanDeclarationsEmpty()
{
HierarchicalConfiguration config = new HierarchicalConfiguration();
setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
decl = new XMLBeanDeclaration(config, KEY);
Map nested = decl.getNestedBeanDeclarations();
assertTrue("Found nested declarations", nested == null
|| nested.isEmpty());
}
/**
* Tests whether interpolation of bean properties works.
*/
public void testGetInterpolatedBeanProperties()
{
HierarchicalConfiguration config = new HierarchicalConfiguration();
String[] varValues = new String[TEST_PROPS.length];
for(int i = 0; i < TEST_PROPS.length; i++)
{
varValues[i] = "${" + VARS + TEST_PROPS[i] + "}";
config.addProperty(VARS + TEST_PROPS[i], TEST_VALUES[i]);
}
setupBeanDeclaration(config, KEY, TEST_PROPS, varValues);
decl = new XMLBeanDeclaration(config, KEY);
checkProperties(decl, TEST_PROPS, TEST_VALUES);
}
/**
* Tests constructing a bean declaration from an undefined key. This should
* cause an exception.
*/
public void testInitFromUndefinedKey()
{
HierarchicalConfiguration config = new HierarchicalConfiguration();
setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
try
{
decl = new XMLBeanDeclaration(config, "undefined_key");
fail("Could create declaration from an undefined key!");
}
catch (IllegalArgumentException iex)
{
// ok
}
}
/**
* Tests constructing a bean declaration from a key, which is undefined when
* the optional flag is set. In this case an empty declaration should be
* created, which can be used for creating beans as long as a default class
* is provided.
*/
public void testInitFromUndefinedKeyOptional()
{
HierarchicalConfiguration config = new HierarchicalConfiguration();
setupBeanDeclaration(config, KEY, TEST_PROPS, TEST_VALUES);
decl = new XMLBeanDeclaration(config, "undefined_key", true);
assertNull("Found a bean class", decl.getBeanClassName());
}
/**
* Tests constructing a bean declaration from a key with multiple values.
* This should cause an exception because keys must be unique.
*/
public void testInitFromMultiValueKey()
{
HierarchicalConfiguration config = new HierarchicalConfiguration();
config.addProperty(KEY, "myFirstKey");
config.addProperty(KEY, "mySecondKey");
try
{
decl = new XMLBeanDeclaration(config, KEY);
fail("Could create declaration from multi-valued property!");
}
catch (IllegalArgumentException iex)
{
// ok
}
}
/**
* Initializes a configuration object with a bean declaration. Under the
* specified key the given properties will be added.
*
* @param config the configuration to initialize
* @param key the key of the bean declaration
* @param names an array with the names of the properties
* @param values an array with the corresponding values
*/
private void setupBeanDeclaration(HierarchicalConfiguration config,
String key, String[] names, String[] values)
{
for (int i = 0; i < names.length; i++)
{
config.addProperty(key + "[@" + names[i] + "]", values[i]);
}
}
/**
* Checks the properties returned by a bean declaration.
*
* @param beanDecl the bean declaration
* @param names an array with the expected property names
* @param values an array with the expected property values
*/
private void checkProperties(BeanDeclaration beanDecl, String[] names,
String[] values)
{
Map props = beanDecl.getBeanProperties();
assertEquals("Wrong number of properties", names.length, props.size());
for (int i = 0; i < names.length; i++)
{
assertTrue("Property " + names[i] + " not contained", props
.containsKey(names[i]));
assertEquals("Wrong value for property " + names[i], values[i],
props.get(names[i]));
}
}
/**
* A helper class used for testing the createBeanDeclaration() factory
* method.
*/
private static class XMLBeanDeclarationTestImpl extends XMLBeanDeclaration
{
public XMLBeanDeclarationTestImpl(SubnodeConfiguration config,
ConfigurationNode node)
{
super(config, node);
}
}
}